package xml.sax.outplm;

import java.io.ByteArrayInputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;

import constants.Globals;
import exception.ExceptionStringHandler;
import exception.IBToolsException;
import exception.IBServiceCallException;

import structures.ServiceCallInfo;
import structures.xmltable.ServiceBaseTypeParameter;
import structures.xmltable.ServiceOutTableTypeParameter;
import structures.xmltable.ServiceOutputBaseTypeParameter;
import structures.xmltable.ServiceParameterTable;
import structures.xmltable.ServiceTableColumn;
import structures.xmltable.ServiceTableTypeParameter;
import structures.xmltable.ServiceTableValue;

import xml.sax.ClassNameLoader;
import xml.sax.JaxbUtil;
import xml.sax.outplm.D.D1;
import xml.sax.outplm.D.Table;
public class PlmOutXMLProcessor implements Globals{

	private static JaxbUtil jaxbUtil;
	
	public static void utilize(){

        String name = ClassNameLoader.getPackageName(new Object() {}.getClass());
        
		jaxbUtil = new JaxbUtil(name);
		jaxbUtil.setRemoveXmlHeaderTag(true);
		jaxbUtil.addMarshallProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

	}

    public static ServiceParameterTable convertXmlStringToTable(String xmlString) throws IBToolsException {
		if (xmlString.indexOf("error") == 1) {
			String exception = xmlString.substring(
					xmlString.indexOf(">") + 1, xmlString.lastIndexOf("<"));
			throw new IBToolsException(new ExceptionStringHandler(true, exception));
		}
    	return convertXmlToTable(xmlString, null);
    }
    public static ServiceParameterTable convertXmlServiceResponseToTable(ServiceCallInfo callInfo) throws IBToolsException, IBServiceCallException {
    	
    	String xmlString = callInfo.getOutXml();
    	
		if (xmlString.indexOf("error") == 1) {
			String errorId = xmlString.substring(xmlString.indexOf("\"") + 1,
					xmlString.lastIndexOf("\""));
			String exception = xmlString.substring(
					xmlString.indexOf(">") + 1, xmlString.lastIndexOf("<"));
			throw new IBServiceCallException(new ExceptionStringHandler(callInfo, new Integer(errorId), exception), callInfo);
		}
    	return convertXmlToTable(xmlString, callInfo);
    }
    
    public static ServiceParameterTable convertXmlToTable(String xmlString, ServiceCallInfo callInfo) throws IBToolsException {
    	if(jaxbUtil == null)
    		utilize();
//    	if(xmlString.indexOf("<d/>") > -1)
//    		xmlString = "<droot/>";
//    	else{
//        	xmlString = xmlString.replaceFirst("<d>", "<droot>");
//        	if(xmlString.lastIndexOf("</d>") > -1)
//        		xmlString = xmlString.substring(0, xmlString.lastIndexOf("</d>")).concat("</droot>");
//        	else {
//        		throw new IBToolsException(new ExceptionStringHandler(true, xmlString));
//        	}
//    	}
    	xmlString = xmlString.replaceAll("", EMPTY_STRING);
        ByteArrayInputStream input = new ByteArrayInputStream (xmlString.getBytes(Charset.forName("UTF8"))); 
        D d = (D) jaxbUtil.unmarshal(input);

        List<ServiceBaseTypeParameter> parameters = new ArrayList<ServiceBaseTypeParameter>();
        List<ServiceTableTypeParameter> tables = new ArrayList<ServiceTableTypeParameter>();

        List<ServiceTableColumn> currentColumns = null;
        
        if(d.d != null)
        for (D1 d1 : d.d) {	
    		List<?> arrayParameterListD2 = (ArrayList<?>) d1.getContent(); //D.D1.D2 veya value
    		if(arrayParameterListD2.size() > 0 && arrayParameterListD2.get(0) instanceof JAXBElement<?>){
    			
    			ServiceTableTypeParameter tableParam = new ServiceOutTableTypeParameter(
    				d1.getId(), EMPTY_STRING);

                List<List<ServiceTableValue>> tvalues = new ArrayList<List<ServiceTableValue>>();
                
        		for (Object d2Object : arrayParameterListD2) {
        			if(d2Object instanceof JAXBElement<?>){ // <d id="this.ListOfBolge_ORGANIZASYONADI">
    					JAXBElement<?> paramD2 = (JAXBElement<?>) d2Object;
    					D.D1.D2 d2 = (D.D1.D2) paramD2.getValue();	// <d n="50070">asd</d>
    					List<ServiceTableValue> valueLine = new ArrayList<ServiceTableValue>();
    					valueLine.add(new ServiceTableValue(d2.getN()));
    					valueLine.add(new ServiceTableValue(d2.getValue()));
    					tvalues.add(valueLine);
        			}
        		}
        		tableParam.setValues(tvalues);
        		tableParam.setColumns(new ArrayList<ServiceTableColumn>());
        		tableParam.addTableColumn("KEY");
        		tableParam.addTableColumn("VALUE");
            	parameters.add(tableParam);
    		}
    		else{
    			String paramName = Globals.EMPTY_STRING;
    			if(arrayParameterListD2.size() > 0){
    				paramName  = arrayParameterListD2.get(0).toString();
    			}
            	ServiceOutputBaseTypeParameter param = new ServiceOutputBaseTypeParameter(
            		d1.getId(), paramName);
            	if(callInfo != null)
            		param.checkDocumentOidStatus(callInfo.getEnvironment());
            	param.analyzeValue();
            	parameters.add(param);
    		}
		}
        if(d.table != null)
        for(Table table : d.table) {
			ServiceTableTypeParameter param = new ServiceOutTableTypeParameter(
					table.getId(), EMPTY_STRING);
            List<List<ServiceTableValue>> tlist = new ArrayList<List<ServiceTableValue>>();
            
			Integer currentLine = null;
			Integer colSize = 0;
			currentColumns = new ArrayList<ServiceTableColumn>();
			for (D.Table.D3 d3 : table.getD() ) {
				if(!colSize.equals(d3.getR())){
					break;
				}
				colSize++;
			}
	        boolean newColumn = true;
			currentLine = 0;
			for (D.Table.D3 d3 : table.getD() ) {
				if(!currentLine.equals(d3.getR())){
					newColumn = true;
					currentLine = d3.getR();
				}
				Integer rInt = (d3.getR() == null) ? 0 : new Integer(d3.getR());
				if(tlist.size() == d3.getR())
					tlist.add(new ArrayList<ServiceTableValue>(colSize));
        		tlist.get(rInt).add(new ServiceTableValue(d3.getValue()));
				if(newColumn){
					currentColumns.add(new ServiceTableColumn(null, d3.getC(), currentColumns.size()));
					newColumn = false;
				}
				currentLine++;
			}
			param.setValues(tlist);
			param.loadColumns(currentColumns);
			tables.add(param);
        }

        ServiceParameterTable serviceParameterTable = new ServiceParameterTable();
        
        for (ServiceBaseTypeParameter serviceBaseTypeParameter : parameters) {
        	serviceParameterTable.add(serviceBaseTypeParameter);
		}
        for (ServiceTableTypeParameter newServiceTableTypeParameter : tables) {
        	serviceParameterTable.add(newServiceTableTypeParameter);
		}
        
        return serviceParameterTable;
        
    }
    
    public static String simpleFormat(String xmlString){
    	if(jaxbUtil == null)
    		utilize();
//    	if(xmlString.indexOf("<d/>") > -1)
//    		xmlString = "<droot/>";
//    	else{
//        	xmlString = xmlString.replaceFirst("<d>", "<droot>");
//        	xmlString = xmlString.substring(0, xmlString.lastIndexOf("</d>")).concat("</droot>");
//    	}
        ByteArrayInputStream input = new ByteArrayInputStream (
        		xmlString
        		.replaceAll("\r\n ", "")
        		.getBytes(Charset.forName("UTF8"))); 
        D droot = (D) jaxbUtil.unmarshal(input);
        xmlString = jaxbUtil.marshal(droot);
        return xmlString;
    }
}
